gdk: Add GType support to GdkContentFormats
authorBenjamin Otte <otte@redhat.com>
Mon, 20 Nov 2017 14:58:17 +0000 (15:58 +0100)
committerBenjamin Otte <otte@redhat.com>
Mon, 20 Nov 2017 22:22:28 +0000 (23:22 +0100)
This is not used by anything yet, but add it now, so people looking at
this new code can make sense of it.
Plus, the documentation mentions it, so better have the docs make sense.

It will be used once we add support for conversions to GDK and allow
doing cipboard/dnd by GValue.

docs/reference/gdk/gdk4-sections.txt
gdk/gdkcontentformats.c
gdk/gdkcontentformats.h
gtk/gtkdragdest.c
gtk/gtktextview.c
tests/testdnd.c

index 008d095b756230ff1fd699d5e35ccec20a934d7d..1eaae400a26e969d00b22a8a81199274ef512b67 100644 (file)
@@ -376,9 +376,11 @@ gdk_content_formats_ref
 gdk_content_formats_unref
 gdk_content_formats_print
 gdk_content_formats_to_string
+gdk_content_formats_get_gtypes
 gdk_content_formats_get_mime_types
 gdk_content_formats_union
 gdk_content_formats_match
+gdk_content_formats_contain_gtype
 gdk_content_formats_contain_mime_type
 
 <SUBSECTION>
@@ -386,6 +388,7 @@ GdkContentFormatsBuilder
 gdk_content_formats_builder_new
 gdk_content_formats_builder_free
 gdk_content_formats_builder_add_formats
+gdk_content_formats_builder_add_gtype
 gdk_content_formats_builder_add_mime_type
 
 <SUBSECTION Private>
index 8cca4797db080ecae0a8efc36d72a1cfe3d4090d..d9ca134f21377d2d874566f8ed00f890577539cb 100644 (file)
@@ -72,6 +72,8 @@ struct _GdkContentFormats
 
   const char **mime_types; /* interned */
   gsize n_mime_types;
+  GType *gtypes;
+  gsize n_gtypes;
 };
 
 G_DEFINE_BOXED_TYPE (GdkContentFormats, gdk_content_formats,
@@ -80,12 +82,16 @@ G_DEFINE_BOXED_TYPE (GdkContentFormats, gdk_content_formats,
 
 
 static GdkContentFormats *
-gdk_content_formats_new_take (const char **mime_types,
-                              guint        n_mime_types)
+gdk_content_formats_new_take (GType *      gtypes,
+                              gsize        n_gtypes,
+                              const char **mime_types,
+                              gsize        n_mime_types)
 {
   GdkContentFormats *result = g_slice_new0 (GdkContentFormats);
   result->ref_count = 1;
 
+  result->gtypes = gtypes;
+  result->n_gtypes = n_gtypes;
   result->mime_types = mime_types;
   result->n_mime_types = n_mime_types;
 
@@ -114,14 +120,14 @@ gdk_content_formats_new (const char **mime_types,
   guint i;
 
   if (n_mime_types == 0)
-      return gdk_content_formats_new_take (NULL, 0);
+      return gdk_content_formats_new_take (NULL, 0, NULL, 0);
 
   array = g_ptr_array_new ();
   for (i = 0; i < n_mime_types; i++)
     g_ptr_array_add (array, (gpointer) g_intern_string (mime_types[i]));
   g_ptr_array_add (array, NULL);
 
-  return gdk_content_formats_new_take ((const char **) g_ptr_array_free (array, FALSE), n_mime_types);
+  return gdk_content_formats_new_take (NULL, 0, (const char **) g_ptr_array_free (array, FALSE), n_mime_types);
 }
 
 /**
@@ -159,6 +165,7 @@ gdk_content_formats_unref (GdkContentFormats *formats)
   if (formats->ref_count > 0)
     return;
 
+  g_free (formats->gtypes);
   g_free (formats->mime_types);
   g_slice_free (GdkContentFormats, formats);
 }
@@ -184,10 +191,16 @@ gdk_content_formats_print (GdkContentFormats *formats,
   g_return_if_fail (string != NULL);
 
   g_string_append (string, "{ ");
-  for (i = 0; i < formats->n_mime_types; i++)
+  for (i = 0; i < formats->n_gtypes; i++)
     {
       if (i > 0)
         g_string_append (string, ", ");
+      g_string_append (string, g_type_name (formats->gtypes[i]));
+    }
+  for (i = 0; i < formats->n_mime_types; i++)
+    {
+      if (i > 0 || formats->n_gtypes > 0)
+        g_string_append (string, ", ");
       g_string_append (string, formats->mime_types[i]);
     }
   g_string_append (string, " }");
@@ -263,29 +276,81 @@ gdk_content_formats_contain_interned_mime_type (const GdkContentFormats *formats
  * gdk_content_formats_match:
  * @first: the primary #GdkContentFormats to intersect
  * @second: the #GdkContentFormats to intersect with
+ * @out_gtype: (out) (allow-none): pointer to take the 
+ *     matching #GType or %G_TYPE_INVALID if @out_mime_type was set.
+ * @out_mime_type: (out) (allow-none) (transfer none): The matching
+ *    mime type or %NULL if @out_gtype is set
  *
  * Finds the first element from @first that is also contained
- * in @second.
+ * in @second. If no matching format is found, %FALSE is returned
+ * and @out_gtype and @out_mime_type are set to %G_TYPE_INVALID and
+ * %NULL respectively.
  *
- * Returns: The first matching #GdkAtom or %NULL if the formatss
- *     do not intersect.
+ * Returns: %TRUE if a matching format was found.
  */
-const char *
+gboolean
 gdk_content_formats_match (const GdkContentFormats *first,
-                           const GdkContentFormats *second)
+                           const GdkContentFormats *second,
+                           GType                   *out_gtype,
+                           const char             **out_mime_type)
 {
   gsize i;
 
-  g_return_val_if_fail (first != NULL, NULL);
-  g_return_val_if_fail (second != NULL, NULL);
+  g_return_val_if_fail (first != NULL, FALSE);
+  g_return_val_if_fail (second != NULL, FALSE);
+
+  if (out_gtype)
+    *out_gtype = G_TYPE_INVALID;
+  if (out_mime_type)
+    *out_mime_type = NULL;
+
+  for (i = 0; i < first->n_gtypes; i++)
+    {
+      if (gdk_content_formats_contain_gtype (second, first->gtypes[i]))
+        {
+          if (out_gtype)
+            *out_gtype = first->gtypes[i];
+          return TRUE;
+        }
+    }
 
   for (i = 0; i < first->n_mime_types; i++)
     {
       if (gdk_content_formats_contain_interned_mime_type (second, first->mime_types[i]))
-        return first->mime_types[i];
+        {
+          if (out_mime_type)
+            *out_mime_type = first->mime_types[i];
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+/**
+ * gdk_content_formats_contain_gtype:
+ * @formats: a #GdkContentFormats
+ * @type: the #GType to search for
+ *
+ * Checks if a given #GType is part of the given @formats.
+ *
+ * Returns: %TRUE if the #GType was found
+ **/
+gboolean
+gdk_content_formats_contain_gtype (const GdkContentFormats *formats,
+                                   GType                    type)
+{
+  g_return_val_if_fail (formats != NULL, FALSE);
+
+  gsize i;
+
+  for (i = 0; i < formats->n_gtypes; i++)
+    {
+      if (type == formats->gtypes[i])
+        return TRUE;
     }
 
-  return NULL;
+  return FALSE;
 }
 
 /**
@@ -295,7 +360,7 @@ gdk_content_formats_match (const GdkContentFormats *first,
  *
  * Checks if a given mime type is part of the given @formats.
  *
- * Returns: %TRUE if the mime_type was found, otherwise %FALSE
+ * Returns: %TRUE if the mime_type was found
  **/
 gboolean
 gdk_content_formats_contain_mime_type (const GdkContentFormats *formats,
@@ -308,6 +373,31 @@ gdk_content_formats_contain_mime_type (const GdkContentFormats *formats,
                                                          g_intern_string (mime_type));
 }
 
+/**
+ * gdk_content_formats_get_gtypes:
+ * @formats: a #GdkContentFormats
+ * @n_gtypes: (out) (allow-none): optional pointer to take the
+ *     number of #GTypes contained in the return value
+ *
+ * Gets the #GTypes included in @formats. Note that @formats may not
+ * contain any #GTypes, in particular when they are empty. In that
+ * case %NULL will be returned. 
+ *
+ * Returns: (transfer none) (nullable): %G_TYPE_INVALID-terminated array of 
+ *     types included in @formats or %NULL if none.
+ **/
+const GType *
+gdk_content_formats_get_gtypes (GdkContentFormats *formats,
+                                gsize             *n_gtypes)
+{
+  g_return_val_if_fail (formats != NULL, NULL);
+
+  if (n_gtypes)
+    *n_gtypes = formats->n_gtypes;
+  
+  return formats->gtypes;
+}
+
 /**
  * gdk_content_formats_get_mime_types:
  * @formats: a #GdkContentFormats
@@ -318,8 +408,9 @@ gdk_content_formats_contain_mime_type (const GdkContentFormats *formats,
  * contain any mime types, in particular when they are empty. In that
  * case %NULL will be returned. 
  *
- * Returns: (transfer none): %NULL-terminated array of interned
- *     strings of mime types included in @formats or %NULL if none.
+ * Returns: (transfer none) (nullable): %NULL-terminated array of 
+ *     interned strings of mime types included in @formats or %NULL
+ *     if none.
  **/
 const char * const *
 gdk_content_formats_get_mime_types (GdkContentFormats *formats,
@@ -343,6 +434,8 @@ gdk_content_formats_get_mime_types (GdkContentFormats *formats,
 
 struct _GdkContentFormatsBuilder
 {
+  GSList *gtypes;
+  gsize n_gtypes;
   GSList *mime_types;
   gsize n_mime_types;
 };
@@ -374,12 +467,20 @@ GdkContentFormats *
 gdk_content_formats_builder_free (GdkContentFormatsBuilder *builder)
 {
   GdkContentFormats *result;
+  GType *gtypes;
   const char **mime_types;
   GSList *l;
   gsize i;
 
   g_return_val_if_fail (builder != NULL, NULL);
 
+  gtypes = g_new (GType, builder->n_gtypes + 1);
+  i = builder->n_gtypes;
+  gtypes[i--] = G_TYPE_INVALID;
+  /* add backwards because most important type is last in the list */
+  for (l = builder->gtypes; l; l = l->next)
+    gtypes[i--] = GPOINTER_TO_SIZE (l->data);
+
   mime_types = g_new (const char *, builder->n_mime_types + 1);
   i = builder->n_mime_types;
   mime_types[i--] = NULL;
@@ -387,8 +488,10 @@ gdk_content_formats_builder_free (GdkContentFormatsBuilder *builder)
   for (l = builder->mime_types; l; l = l->next)
     mime_types[i--] = l->data;
 
-  result = gdk_content_formats_new_take (mime_types, builder->n_mime_types);
+  result = gdk_content_formats_new_take (gtypes, builder->n_gtypes,
+                                         mime_types, builder->n_mime_types);
 
+  g_slist_free (builder->gtypes);
   g_slist_free (builder->mime_types);
   g_slice_free (GdkContentFormatsBuilder, builder);
 
@@ -412,12 +515,35 @@ gdk_content_formats_builder_add_formats (GdkContentFormatsBuilder *builder,
   g_return_if_fail (builder != NULL);
   g_return_if_fail (formats != NULL);
 
+  for (i = 0; i < formats->n_gtypes; i++)
+    gdk_content_formats_builder_add_gtype (builder, formats->gtypes[i]);
+
   for (i = 0; i < formats->n_mime_types; i++)
     gdk_content_formats_builder_add_mime_type (builder, formats->mime_types[i]);
 }
 
 /**
- * gdk_content_formats_builder_add_formats:
+ * gdk_content_formats_builder_add_gtype:
+ * @builder: a #GdkContentFormatsBuilder
+ * @type: a #GType
+ *
+ * Appends @gtype to @builder if it has not already been added.
+ **/
+void
+gdk_content_formats_builder_add_gtype (GdkContentFormatsBuilder *builder,
+                                       GType                     type)
+{
+  g_return_if_fail (builder != NULL);
+
+  if (g_slist_find (builder->gtypes, GSIZE_TO_POINTER (type)))
+    return;
+
+  builder->gtypes = g_slist_prepend (builder->gtypes, GSIZE_TO_POINTER (type));
+  builder->n_gtypes++;
+}
+
+/**
+ * gdk_content_formats_builder_add_mime_type:
  * @builder: a #GdkContentFormatsBuilder
  * @mime_type: a mime type
  *
index 2bb1e1766f82954323f5e6e42a85cfbade921be7..7ba149631623f8bb6c652086d118fbcea0cfc224 100644 (file)
@@ -46,6 +46,9 @@ void                    gdk_content_formats_print               (GdkContentForma
 GDK_AVAILABLE_IN_3_94
 char *                  gdk_content_formats_to_string           (GdkContentFormats              *formats);
 
+GDK_AVAILABLE_IN_3_94
+const GType *           gdk_content_formats_get_gtypes          (GdkContentFormats              *formats,
+                                                                 gsize                          *n_gtypes);
 GDK_AVAILABLE_IN_3_94
 const char * const *    gdk_content_formats_get_mime_types      (GdkContentFormats              *formats,
                                                                  gsize                          *n_mime_types);
@@ -54,8 +57,13 @@ GDK_AVAILABLE_IN_3_94
 GdkContentFormats *     gdk_content_formats_union               (GdkContentFormats              *first,
                                                                  const GdkContentFormats        *second) G_GNUC_WARN_UNUSED_RESULT;
 GDK_AVAILABLE_IN_3_94
-const char *            gdk_content_formats_match               (const GdkContentFormats        *first,
-                                                                 const GdkContentFormats        *second);
+gboolean                gdk_content_formats_match               (const GdkContentFormats        *first,
+                                                                 const GdkContentFormats        *second,
+                                                                 GType                          *out_gtype,
+                                                                 const char                    **out_mime_type);
+GDK_AVAILABLE_IN_3_94
+gboolean                gdk_content_formats_contain_gtype       (const GdkContentFormats        *formats,
+                                                                 GType                           type);
 GDK_AVAILABLE_IN_3_94
 gboolean                gdk_content_formats_contain_mime_type   (const GdkContentFormats        *formats,
                                                                  const char                     *mime_type);
@@ -72,6 +80,9 @@ void                    gdk_content_formats_builder_add_formats (GdkContentForma
 GDK_AVAILABLE_IN_3_94
 void                    gdk_content_formats_builder_add_mime_type(GdkContentFormatsBuilder      *builder,
                                                                  const char                     *mime_type);
+GDK_AVAILABLE_IN_3_94
+void                    gdk_content_formats_builder_add_gtype   (GdkContentFormatsBuilder       *builder,
+                                                                 GType                           type);
 
 G_END_DECLS
 
index 9c37569fb1e66a611b67c3785fd62971a4770376..8b9fbff74f9a1cb18ea95f974b1e2bc5291f605a 100644 (file)
@@ -422,8 +422,10 @@ gtk_drag_dest_find_target (GtkWidget         *widget,
   if (target_list == NULL)
     return NULL;
 
-  result = gdk_content_formats_match (target_list,
-                                      gdk_drag_context_get_formats (context));
+  gdk_content_formats_match (target_list,
+                             gdk_drag_context_get_formats (context),
+                             NULL,
+                             &result);
 
   return result;
 }
index a4bf36d5d60726db55592b9d24f33c0a3cd26718..3f24ec459b07c51b2469148cc75ec937fc249256 100644 (file)
@@ -8150,7 +8150,7 @@ gtk_text_view_drag_data_received (GtkWidget        *widget,
           GdkAtom *atoms;
           gint     n_atoms;
           GdkContentFormats *dnd_formats, *buffer_formats;
-          GdkAtom  target = NULL;
+          const char *target = NULL;
 
           copy_tags = FALSE;
 
@@ -8158,7 +8158,7 @@ gtk_text_view_drag_data_received (GtkWidget        *widget,
           buffer_formats = gdk_content_formats_new (atoms, n_atoms);
           dnd_formats = gdk_drag_context_get_formats (context);
 
-          target = gdk_content_formats_match (dnd_formats, buffer_formats);
+          gdk_content_formats_match (dnd_formats, buffer_formats, NULL, &target);
 
           gdk_content_formats_unref (buffer_formats);
           g_free (atoms);
index c3c16dfc5827a2249f815fb44c91fc3b21444715..3fbc0f6f2d62181c94dd4571622d8e9b9d491893 100644 (file)
@@ -352,7 +352,7 @@ target_drag_drop       (GtkWidget          *widget,
   gtk_image_set_from_pixbuf (GTK_IMAGE (widget), trashcan_closed);
 
   formats = gdk_drag_context_get_formats (context);
-  format = gdk_content_formats_match (formats, formats);
+  gdk_content_formats_match (formats, formats, NULL, &format);
   if (format)
     {
       gtk_drag_get_data (widget, context,